#include "sms.h"

static void update_deamon_check_build_num();
static gboolean update_deamon_load_update_xml(char *filename, UpdateDeamon *deamon);
static void update_deamon_download_update_resource_file(UpdateDeamon *deamon);
static gboolean update_deamon_free(UpdateDeamon *deamon);

static char *update_deamon_compose_path(char *result, const char *path, const char *filename) {
	printf("~~~%s\n" ,__FUNCTION__);
	strcpy(result, path);
	return strcat(result, filename);
}

static int update_deamon_copy_build_num_file(const char *dest_file_path, const char *src_file_path) {
	char cmd[512];
	sprintf(cmd, "cp %s %s", src_file_path, dest_file_path);
	return system(cmd);
}

static void update_deamon_set_layout_update_tag(UpdateDeamon *deamon) {
	SMS *sms = (SMS *)deamon->sms;
	int i;
	for(i= 0; i<deamon->update_layout_count; i++) {
		sms->wins[deamon->update_layout_array[i]]->needreload = TRUE;
	}

	for(i= 0; i<LAYOUT_WIN_COUNT; i++) {
		printf("i: %d\n", i);
		if(sms->wins[i]->needreload)
		{
			printf("win[%d]: needreload\n", i);
		}
	}
}

//gboolean update_deamon_reload_layout(UpdateDeamon *deamon)

static gboolean update_deamon_build_num_download_finish(Downloader *downloader, gpointer data) {
	printf("~~~%s\n" ,__FUNCTION__);

	UpdateDeamon *deamon = data;
	downloader_delete(deamon->build_num_downloader);
	deamon->build_num_downloader = NULL;
	deamon->download_what = DOWNLOAD_NONE;
	update_deamon_check_build_num(deamon);
	return TRUE;
}

static gboolean update_deamon_update_xml_download_finish(Downloader *downloader, gpointer data) {
	printf("~~~%s\n" ,__FUNCTION__);

	UpdateDeamon *deamon = data;
	downloader_delete(deamon->update_xml_downloader);
	deamon->update_xml_downloader = NULL;
	deamon->download_what = DOWNLOAD_NONE;
	update_deamon_load_update_xml(UPDATE_XML_FILE_LOCAL_PATH, deamon);
	deamon->resource_file_download_count = 0;
	update_deamon_download_update_resource_file(deamon);
	return TRUE;
}

static gboolean update_deamon_resource_download_finish(Downloader *downloader, gpointer data)
{
	printf("~~~%s\n" ,__FUNCTION__);

	UpdateDeamon *deamon = data;
	downloader_delete(deamon->resource_downloader);
	deamon->resource_downloader = NULL;
	//printf("cur_build: %d\n", deamon->cur_build_num);
	deamon->download_what = DOWNLOAD_NONE;
    deamon->resource_file_download_count += 1;
	printf("resource_file_download_count: %d\n", deamon->resource_file_download_count);

	if (deamon->resource_file_download_count == deamon->update_file_count) {
		//printf ("ready to free deamon\n");
		deamon->isAllResourceDownload = TRUE;
        deamon->cur_build_num = deamon->new_build_num;
        update_deamon_copy_build_num_file(BUILD_NUM_FILE_LOCAL_PATH, BUILD_NUM_FILE_TMP_PATH);
        update_deamon_set_layout_update_tag(deamon);
        update_deamon_free (deamon);
        return TRUE;
	}
	update_deamon_download_update_resource_file(deamon);

	return TRUE;
}

static gboolean update_deamon_download_error(Downloader *downloader, gpointer data) {
	printf("~~~%s\n" ,__FUNCTION__);
	downloader_delete(downloader);
	UpdateDeamon *deamon = data;
	//deamon->downloader = NULL;
	deamon->build_num_downloader = NULL;
	deamon->update_xml_downloader = NULL;
	deamon->resource_downloader = NULL;
	deamon->download_status = UPDATEDEAMON_DOWNLOAD_ERROR;
	deamon->download_what = DOWNLOAD_NONE;
	return TRUE;
}

static gboolean update_deamon_download_progress(Downloader *downloader, gpointer data) {
	printf("~~~%s\n" ,__FUNCTION__);
	UpdateDeamon *deamon = data;
	deamon->download_status = UPDATEDEAMON_DOWNLOAD_DOWNLOADING;
	return TRUE;
}

static void update_deamon_downloadfile(UpdateDeamon *deamon, const char *download_file, const char *output_file) {
	printf("~~~%s\n" ,__FUNCTION__);
	Downloader *downloader;

    downloader = downloader_new(download_file, output_file, -1, deamon);

    if (deamon->download_what == DOWNLOAD_BUILD_NUM_FILE) {
    	deamon->build_num_downloader = downloader;
    	if(!deamon->build_num_downloader) {
    		fprintf(stderr,"%s:Creat downloader error\n",__FUNCTION__);
    	}
    	downloader_set_func(downloader,"download-finish", update_deamon_build_num_download_finish);
    } else if (deamon->download_what == DOWNLOAD_UPDATE_XML_FILE) {
    	deamon->update_xml_downloader = downloader;
    	if(!deamon->update_xml_downloader) {
    		fprintf(stderr,"%s:Creat downloader error\n",__FUNCTION__);
    	}
    	downloader_set_func(downloader,"download-finish", update_deamon_update_xml_download_finish);
    } else if (deamon->download_what == DOWNLOAD_RESOURCE_FILE) {
    	deamon->resource_downloader = downloader;
    	if(!deamon->resource_downloader) {
    		fprintf(stderr,"%s:Creat downloader error\n", __FUNCTION__);
    	}
    	downloader_set_func(downloader,"download-finish", update_deamon_resource_download_finish);
    }


	downloader_set_func(downloader,"download-error",update_deamon_download_error);
	downloader_set_func(downloader,"download-progress",update_deamon_download_progress);
	downloader_run(downloader);

}

static int update_deamon_get_build_num_from_file(const char *filename) {
	printf("~~~%s\n" ,__FUNCTION__);
	FILE *fp;
	char str[20];
	
	if((fp=fopen(filename, "r"))==NULL) {
        printf("can not open the build num file");
	    return -1;
	}
	fgets(str, sizeof(str), fp);
	fclose(fp);
	return atoi(str);
}

static gboolean update_deamon_free(UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	int i;
	if(deamon->remote_path_array) {
		for(i=0; i<deamon->update_file_count; i++)
			free(deamon->remote_path_array[i]);
	}
	if(deamon->local_path_array) {
		for(i=0; i<deamon->update_file_count; i++)
			free(deamon->local_path_array[i]);
	}
	if (deamon->build_num_downloader) {
		free(deamon->build_num_downloader);
		deamon->build_num_downloader = NULL;
	}
	if (deamon->update_xml_downloader) {
		free(deamon->update_xml_downloader);
		deamon->update_xml_downloader = NULL;
	}
	if (deamon->resource_downloader) {
		free(deamon->resource_downloader);
		deamon->resource_downloader = NULL;
	}
}

static gboolean update_deamon_init(UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	if (deamon == NULL)
		return FALSE;
	deamon->cur_build_num = update_deamon_get_build_num_from_file(BUILD_NUM_FILE_LOCAL_PATH);
	deamon->new_build_num = deamon->cur_build_num;
	deamon->download_status = UPDATEDEAMON_DOWNLOAD_NONE;
	deamon->download_what = DOWNLOAD_NONE;
	deamon->resource_file_download_count = 0;
	deamon->isAllResourceDownload = FALSE;
	deamon->remote_path_array = NULL;
	deamon->local_path_array = NULL;
	deamon->build_num_downloader = NULL;
	deamon->update_xml_downloader = NULL;
	deamon->resource_downloader = NULL;
	deamon->update_file_count = 0;
	deamon->resource_file_download_count = 0;
	return TRUE;
}

UpdateDeamon *update_deamon_new(gpointer sms) {
	printf("~~~%s\n" ,__FUNCTION__);
	UpdateDeamon *deamon = NULL;
	deamon = (UpdateDeamon *) g_malloc0(sizeof(UpdateDeamon)+1);
	deamon->sms = sms;
	deamon->cur_build_num = 0;
	deamon->update_timeout = 7200000; //timeout is 2 hours
	return deamon;
}

static void update_deamon_download_update_resource_file(UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	//int i;
	deamon->download_what = DOWNLOAD_RESOURCE_FILE;
	int num = deamon->resource_file_download_count;
	update_deamon_downloadfile(deamon, deamon->remote_path_array[num], deamon->local_path_array[num]);

}

static void update_deamon_check_build_num(UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	deamon->new_build_num = update_deamon_get_build_num_from_file(BUILD_NUM_FILE_TMP_PATH);
	if (deamon->cur_build_num < deamon->new_build_num) {
		deamon->download_what = DOWNLOAD_UPDATE_XML_FILE;
		update_deamon_downloadfile(deamon, UPDATE_XML_FILE_REMOTE_PATH, UPDATE_XML_FILE_LOCAL_PATH);
	}
}

gboolean update_deamon_timeout_update(UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	gboolean ret = FALSE;
		ret = update_deamon_init(deamon);
	deamon->download_what = DOWNLOAD_BUILD_NUM_FILE;
	update_deamon_downloadfile(deamon, BUILD_NUM_FILE_REMOTE_PATH, BUILD_NUM_FILE_TMP_PATH);
	return ret;
}

static gboolean update_deamon_travel_update_file(xmlNode *a_node, UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	xmlNode *cur_node = NULL;
	int build_id;
	xmlChar *val;
	int id = 0;

	if(strcmp(a_node->name,"update-file") == 0) {
		build_id = sms_get_xml_int(a_node, "build", 0);
	    if (build_id != deamon->new_build_num)
	    	return FALSE;
		deamon->update_file_count = sms_get_xml_int(a_node, "update_file_count", 0);
	} else
		return FALSE;

	deamon->remote_path_array = (char **)g_malloc0(sizeof(char *)*deamon->update_file_count + 1);
	deamon->local_path_array = (char **)g_malloc0(sizeof(char *)*deamon->update_file_count + 1);

	for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
		if (cur_node->type == XML_ELEMENT_NODE){
			printf("node type: Element, name: %s\n", cur_node->name);
			if(strcmp(cur_node->name, "file")==0) {
				val = xmlGetProp (cur_node, (xmlChar*)"remote_path");
				//printf("remote_path: %s\n", val);
				deamon->remote_path_array[id] = (char *)val;
				val = xmlGetProp (cur_node, (xmlChar*)"local_path");
				//printf("local_path: %s\n", val);
				deamon->local_path_array[id] = (char *)val;
				++id;
			}
		}
	}
	return TRUE;
}

static gboolean update_deamon_travel_update_layout(xmlNode *a_node, UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
		xmlNode *cur_node = NULL;
		int build_id;
		int id = 0;

		if(strcmp(a_node->name,"update-layout") == 0) {
			build_id = sms_get_xml_int(a_node, "build", 0);
		    if (build_id != deamon->new_build_num)
		    	return FALSE;
			deamon->update_layout_count = sms_get_xml_int(a_node, "update_layout_count", 0);
		} else
			return FALSE;

		deamon->update_layout_array = (int *)g_malloc0(sizeof(int)*deamon->update_layout_count + 1);

		for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
			if (cur_node->type == XML_ELEMENT_NODE){
				printf("node type: Element, name: %s\n", cur_node->name);
				if(strcmp(cur_node->name, "layout")==0) {
					deamon->update_layout_array[id] = sms_get_xml_int(cur_node, "id", -1);
					++id;
				}
			}
		}
		return TRUE;
}

static gboolean update_deamon_load_update_xml(char *filename, UpdateDeamon *deamon) {
	printf("~~~%s\n" ,__FUNCTION__);
	gboolean ret=FALSE;
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	xmlNode *cur_node = NULL;
	xmlNode *child_node = NULL;
	xmlNode *update_file_node = NULL;
	xmlNode *update_layout_node = NULL;

	doc = xmlReadFile(filename, NULL, 0);
	if (doc == NULL) {
		fprintf(stderr,"error: could not parse file %s\n", filename);
		return ret;
	}
	root_element = xmlDocGetRootElement(doc);

	if(root_element)
	{
		for (cur_node = root_element; cur_node; cur_node = cur_node->next) {
			if (cur_node->type == XML_ELEMENT_NODE) {
				ret = TRUE;
				break;
			}
		}

		for (child_node = root_element->children; child_node; child_node = child_node->next) {
			if (child_node->type == XML_ELEMENT_NODE) {
				printf("node type: Element, name: %s\n", child_node->name);
				if(strcmp(child_node->name, "update-file")==0)
				    update_file_node=child_node;
			    else if(strcmp(child_node->name, "update-layout")==0)
					update_layout_node=child_node;
			}
		}

		if(!update_file_node || !update_layout_node)
			return FALSE;
		ret=update_deamon_travel_update_file(update_file_node, deamon);
		ret &= update_deamon_travel_update_layout(update_layout_node, deamon);
    }
	xmlFreeDoc(doc);
	xmlCleanupParser();
	return ret;
}



